/************************************************************************/
/*	Perlin Production Co. Ltd. July 2012				*/
/*	GAS, bi-directional Alpha Sprite image Generator, v.2.1		*/
/************************************************************************/
/* GASLib.C */

#include "stdio.h"
#include "fdlib.h"
#include "gas.h"

/* InitParm(ip++, 'd', 1, DEFSD	, MAXSD	, "sprite depth"); */

InitParm(_ip, _key, _min, _val, _max, _name) /*ctor*/
INTPARM* _ip;
char	_key;
int	_min;
int	_val;
int	_max;
char	*_name;
{
	_ip->ip_key	= _key;
	_ip->ip_rep	= 0; 	/* 0 to avoid multiple value redefinitions */
	_ip->ip_min	= _min;
	_ip->ip_val	= _val;	/* defaul value originally */
	_ip->ip_max	= _max;
	_ip->ip_name	= _name;
}
	


INTPARM* FindParm(_param, _key, _numparm)
INTPARM		*_param;
char		_key;
unsigned	_numparm;
{
	int	i;
	INTPARM	*result;
	
	result = 0;
	
	for (i=result; !result && i < _numparm; ++i)
	{
		if (_param->ip_key == tolower(_key)) result = _param;
		else ++_param;
	}
	return result;
}
			


OptParm(_argv, _argb, _argc, _param, _numparm)
char		**_argv;
int		_argb;
int		_argc;
INTPARM		*_param;
unsigned	_numparm;
{
	int	i;
	char	*option;
	INTPARM	*found;
	
	for (i=_argb; i < _argc; ++i)
	{
		option	= _argv[i];
		if ((*option != '-') || (*(option+2) != '='))
			trouble("invalid input at", option);
			
		found = FindParm(_param, *++option, _numparm);
		if (found)
		{
		 if (found->ip_rep++)
			trouble("parameter redefinition", found->ip_name);
		 option += 2;
		 found->ip_val = ArgInt(option, found->ip_min
		 			, found->ip_max, found->ip_name);
		 printf("%s is set to %d\n",found->ip_name, found->ip_val);
		}			
	}		
}




char* SFTxt(_id)
unsigned _id;
{
	switch(_id)
	{
		case SF_ANY: return "any";
		case SF_PBP: return "plane-by-plane";
		case SF_PTP: return "pixel-through-planes";
		case SF_BTP: return "byte-through-planes";
		case SF_WBC: return "bi-directional words";
		case SF_ABC: return "bi-directonal alpha";
		default: return 0;
	}
}
	


usage(_text)
char* _text;
{
 rev_vid();
 printf("GAS width height alpha image output [options]\n");
 nrm_vid();
 printf("WIDTH  - sprite width, bytes  1..%d\n", MAXSW);
 printf("HEIGHT - sprite height,pixels 1..%d\n", MAXSH);
 printf("ALPHA  - sprite alpha bitmap file\n");
 printf("IMAGE  - sprite image bitmap file\n");
 printf("OUTPUT - converted file\n");
 printf("\toptional parameters\n");
 printf("-p=[%d] - number of shifted image phases 1..%d\n", DEFPHS, MAXPHS);
 printf("-d=[%d] - sprite depth, planes 1..%d\n", DEFSD, MAXSD);
 printf("-f=[%d==%s] - input files format, 0=any\n",SF_DEF,SFTxt(SF_DEF));
 printf("-m=[0] - mirror input alpha and image bitmaps\n");
 printf("-i=[%d] - colour mode 0-normal, 1-inverted bits\n",DEFINV);
 printf("-x=[0] - MIXING mode: suppress input conversion to Aplha Sprite\n");
 
 
 if (_text)
 {
	printf("\n");
	trouble(_text, 0);
	printf("0x7");
 }
}



banner(_text)
char* _text;
{
 printf("Perlin Production Co. Ltd. August 2012\n");
 printf("GAS, bi-directional Alpha Sprite image Generator / mixer, ver. 3.2\n");
 printf("Interleaves [optionally converts] input files to aplha sprite format.\n");
 printf("If phases > 1, output is ");
 rev_vid();
 printf("8 pixels wider");
 nrm_vid();
 printf(", shifted 8/phases bits right.\n");
 printf("Inverted mode (alpha-transparent): img=(~img & ~alpha), alpha =alpha\n");
 printf("Normal   mode (image-transparent): img=img            , alpha =~alpha\n");
 printf("\n");
 usage(_text);
}



ReadFD(_fd, _depth, _width, _height, _incwdt)
FD*		_fd;
unsigned	_depth;
unsigned	_width;
unsigned	_height;
int		_incwdt;
{
	unsigned i;
	unsigned szRead, szPlane, szRdAll;
	char	*p;

	szRead	= _width * _height;
	szPlane	= (_width + _incwdt) * _height;
	szRdAll	= _depth * szPlane;

	if (_fd->bufsiz != szRdAll)
		trouble("invalid buffer size in",_fd->name);

	p = _fd->buf;

	for (i=0; i < _depth; ++i)
	{
		if ((read(_fd->file,p,szRead)) != szRead)
			trouble("read error in",_fd->name);

		p += szPlane;
	}
}


InvBuf(_fd)
FD*	_fd;
{
 unsigned	i;
 unsigned	size;
 char*		p;

 size	= _fd->bufsiz;
 p	= _fd->buf;

 for (i=0; i < size; ++i) p[i] = ~p[i];
}


InvPln(_fd,_depth,_width,_height)
FD*		_fd;
unsigned	_depth;
unsigned	_width;
unsigned	_height;
{
	char		*l,*r,tmp;
	unsigned	i,j,dhalf,size,size2;

	if (_depth < 2) return;

	dhalf	= _depth / 2;
	size	= _width * _height;
	size2	= size * 2;
	l	= _fd->buf;
	r	= l + (_depth - 1) * size;

	for (i=0; i < dhalf; ++i)
	{
		for (j=0; j < size; ++j) *l++ = *r++;
		r -= size2;
 	}
}


RarBuf(_fd, _lmask, _amt, _depth, _width, _height)
FD*		_fd;
char		_lmask;
unsigned	_amt;	/* amount of rotation right 1..7 */
unsigned	_depth;
unsigned	_width;
unsigned	_height;
{
	unsigned	d,w,h;
	unsigned	szPlane;
	char		*p, *plane;
	unsigned char	c, mask, lamt;

	_amt	&= 7;

	if (!_amt) return;	/* 1 */

	lamt	= 8 - _amt;	/* 7 */
	plane	= _fd->buf;
	szPlane	= _width * _height;

	for(d=0; d < _depth; ++d)
	{
 		for(h=0; h < _height;++h)
		{
			p	= plane + h;
			mask	= _lmask << lamt;

		 	for(w=0; w < _width; ++w)
	 		{
				c	= *p;
				*p	= (c >> _amt) | mask;
				mask	= c << lamt;

				p += _height;
			}
		
		}
		plane += szPlane;
	}
}





Mirror	(_byte)
char	_byte;
{
	int	i,j;
	char	result;
	 
	result	= 0;
	j	= 0x1;
	 
	for (i=0x80 ; i ; i >>= 1)
	{
		if (_byte & i)	result |= j;
		j <<= 1;
	}
	return result;
}
		

	

MirBuf(_fd, _depth, _width, _height)
FD*		_fd;
unsigned	_depth;
unsigned	_width;
unsigned	_height;
{
	unsigned	d,w,h,wh;
	char		*plane, c;
	char		*pBeg, *pEnd;
	unsigned	szPlane, szLine;
	
	plane	= _fd->buf;
	szPlane	= _width * _height;
	szLine	= szPlane - _height;
	wh	= _width/2 + (_width & 0x1);
	
	for(d=0; d < _depth; ++d)
	{
	 for(h=0; h < _height;++h)
	 {
		pBeg = plane + h;	/* step is +_height */
		pEnd = pBeg + szLine;	/* step is -_height */
		
		for(w=0; w < wh; ++w)
		{
			c	= Mirror(*pBeg);
			*pBeg	= Mirror(*pEnd);
			*pEnd	= c;
			pBeg 	+= _height;
			pEnd	-= _height;
			
		}
	 }
	 plane += szPlane;
	}
}




DisInp	(_name,_size)
char		*_name;
unsigned	_size;
{
	FILE*	fd;
	char	*d;
	char	dpname[20];

	strncpy(dpname,_name,12); /* 0/a:12345678 */
	for (d=dpname ; *d ; ++d )
		if (*d == '.')
		{
			*d = 0;
			break;
		}
	strcat(dpname,".DIS");

	printf("\nGenerating disassembler input pipeline %s ",dpname);

	if (fd = fopen(dpname,"w",128))
	{
		fprintf(fd,"%x\n0\n0\n",_size);
		printf(".");
		fprintf(fd,"NNYNNNNY0-%x\n\n\n",_size);
		printf(".");
		fclose(fd);
		printf(". succeded\n");
	}
	else printf("failed\n");
}
